/**
 * 网络请求工具类
 * 封装uni.request请求，统一处理请求拦截、响应拦截和错误处理
 * 支持模拟数据模式，便于前端开发和测试
 */
import { ref } from 'vue';
import * as mockData from './mock.js';

// 后端API基础路径
const BASE_URL = 'http://localhost:8080/api';

// 请求超时时间(毫秒)
const TIMEOUT = 10000;

// 模拟数据模式，当后端服务不可用时自动使用模拟数据
const USE_MOCK = true;

/**
 * 请求拦截器
 * @param {Object} options 请求配置
 * @returns {Object} 处理后的请求配置
 */
function requestInterceptor(options) {
  console.log('请求拦截器处理(new):', options.url);
  
  // 获取token，优先检查标准存储位置
  let token = uni.getStorageSync('token');
  
  // 如果没找到，尝试其他可能的存储位置
  if (!token) {
    const tokenInfo = uni.getStorageSync('tokenInfo');
    if (tokenInfo) {
      try {
        const parsedInfo = JSON.parse(tokenInfo);
        if (parsedInfo && parsedInfo.value) {
          token = parsedInfo.value;
          console.log('从 tokenInfo 获取到 token');
        }
      } catch (e) {
        console.error('解析 tokenInfo 失败:', e);
      }
    }
  }
  
  // 如果还没有，尝试检查Authorization键
  if (!token) {
    const authHeader = uni.getStorageSync('Authorization');
    if (authHeader && authHeader.startsWith('Bearer ')) {
      token = authHeader.substring(7); // 删除 'Bearer ' 前缀
      console.log('从 Authorization 获取到 token');
    }
  }
  
  // 防止使用无效token
  if (token && typeof token === 'string' && token.trim() !== '') {
    // 检查token是否是JWT格式 (至少应该有两个点分隔三部分)
    if (token.split('.').length !== 3) {
      console.warn('检测到不符合JWT格式的token:', token.substring(0, 10) + '...');
    } else {
      console.log('添加有效token到请求头:', token.substring(0, 10) + '...');
    }
    
    // 添加到请求头
    options.header = {
      ...options.header,
      'Authorization': `Bearer ${token}`
    };
  } else {
    console.warn('没有发现有效的token用于请求:', options.url);
  }
  
  // 添加内容类型头
  if (options.method === 'POST' || options.method === 'PUT') {
    options.header = {
      ...options.header,
      'Content-Type': options.header?.['Content-Type'] || 'application/json'
    };
  }
  
  return options;
}

/**
 * 响应拦截器
 * @param {Object} response 响应数据
 * @returns {Object|Promise} 处理后的响应数据或Promise对象
 */
function responseInterceptor(response) {
  const { data, statusCode } = response;
  
  // 请求成功
  if (statusCode >= 200 && statusCode < 300) {
    // 如果后端返回的格式是 { code, message, data }
    if (data && data.hasOwnProperty('code')) {
      if (data.code === 200 || data.code === 0) {
        return data;
      } else {
        // 业务错误
        const error = new Error(data.message || '业务处理失败');
        error.code = data.code;
        error.data = data;
        return Promise.reject(error);
      }
    }
    
    // 直接返回数据
    return data;
  }
  
  // 请求失败
  const error = new Error(data?.message || '请求失败');
  error.statusCode = statusCode;
  error.data = data;
  
  // 处理特定状态码
  switch (statusCode) {
    case 401:
      // 未授权，清除token并跳转到登录页
      uni.removeStorageSync('token');
      uni.removeStorageSync('userInfo');
      uni.showToast({
        title: '登录已过期，请重新登录',
        icon: 'none'
      });
      setTimeout(() => {
        uni.navigateTo({
          url: '/pages/login/login'
        });
      }, 1500);
      break;
    case 403:
      uni.showToast({
        title: '您没有权限进行此操作',
        icon: 'none'
      });
      break;
    case 404:
      uni.showToast({
        title: '请求的资源不存在',
        icon: 'none'
      });
      break;
    case 500:
      uni.showToast({
        title: '服务器内部错误',
        icon: 'none'
      });
      break;
    default:
      uni.showToast({
        title: error.message || '请求失败',
        icon: 'none'
      });
  }
  
  return Promise.reject(error);
}

/**
 * 获取模拟数据
 * @param {Object} options 请求配置
 * @param {Boolean} forceMock 强制使用模拟数据
 * @returns {Object|null} 模拟数据或空
 */
function getMockData(options, forceMock = false) {
  if (!USE_MOCK && !forceMock) return null;
  
  const url = options.url;
  const method = options.method;
  const params = method === 'GET' ? options.data : {};
  
  // 根据URL路径和参数匹配模拟数据
  if (url.includes('/recommendations/hot')) {
    return { list: mockData.mockHotBooks, total: mockData.mockHotBooks.length };
  }
  
  if (url.includes('/recommendations/new')) {
    return { list: mockData.mockNewBooks, total: mockData.mockNewBooks.length };
  }
  
  if (url.includes('/recommendations/personal')) {
    return { list: mockData.mockPersonalRecommendations, total: mockData.mockPersonalRecommendations.length };
  }
  
  if (url.includes('/categories')) {
    return { list: mockData.mockCategories, total: mockData.mockCategories.length };
  }
  
  if (url.includes('/analysis/sales-ranking')) {
    return { data: mockData.mockSalesRanking };
  }
  
  if (url.includes('/analysis/rating-distribution')) {
    return { data: mockData.mockRatingDistribution };
  }
  
  if (url.includes('/analysis/hot-keywords')) {
    return { data: mockData.mockHotKeywords };
  }
  
  if (url.includes('/analysis/market-trend')) {
    const granularity = params.granularity || 'day';
    return { data: mockData.mockMarketTrend(granularity) };
  }
  
  return null;
}

/**
 * 通用请求方法
 * @param {Object} options 请求配置
 * @returns {Promise} 请求Promise对象
 */
function request(options) {
  // 合并请求选项
  options = {
    url: options.url,
    method: options.method || 'GET',
    data: options.data,
    header: options.header || {},
    timeout: options.timeout || TIMEOUT,
    dataType: options.dataType || 'json',
    responseType: options.responseType || 'text',
    ...options
  };
  
  // 处理URL
  if (options.url.indexOf('http') !== 0) {
    options.url = `${BASE_URL}${options.url}`;
  }
  
  // 应用请求拦截器
  options = requestInterceptor(options);
  
  // 如果启用了模拟数据模式，尝试返回模拟数据
  if (USE_MOCK) {
    const mockResult = getMockData(options);
    if (mockResult) {
      console.log(`[模拟数据] 返回数据：${options.url}`, mockResult);
      return Promise.resolve({
        data: mockResult,
        statusCode: 200,
        header: {},
        cookies: []
      });
    }
  }
  
  // 发送请求
  return new Promise((resolve, reject) => {
    uni.request({
      ...options,
      success: (res) => {
        try {
          // 应用响应拦截器
          const result = responseInterceptor(res);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      },
      fail: (err) => {
        console.error(`请求失败: ${options.url}`, err);
        
        // 若请求失败且启用了模拟数据模式，再尝试获取模拟数据
        if (USE_MOCK) {
          const mockResult = getMockData(options, true);
          if (mockResult) {
            console.log(`[模拟数据] 请求失败后返回模拟数据：${options.url}`, mockResult);
            resolve({
              data: mockResult,
              statusCode: 200,
              header: {},
              cookies: []
            });
            return;
          }
          uni.showToast({
            title: '网络连接失败，请检查网络设置',
            icon: 'none'
          });
        }
        
        // 修复了这里的变量名错误，从error改为err
        reject(err);
      }
    });
  });
}

/**
 * GET请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {Object} options 其他配置项
 * @returns {Promise} 请求Promise对象
 */
function get(url, data = {}, options = {}) {
  return request({
    url,
    method: 'GET',
    data,
    ...options
  });
}

/**
 * POST请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {Object} options 其他配置项
 * @returns {Promise} 请求Promise对象
 */
function post(url, data = {}, options = {}) {
  return request({
    url,
    method: 'POST',
    data,
    ...options
  });
}

/**
 * PUT请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {Object} options 其他配置项
 * @returns {Promise} 请求Promise对象
 */
function put(url, data = {}, options = {}) {
  return request({
    url,
    method: 'PUT',
    data,
    ...options
  });
}

/**
 * DELETE请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {Object} options 其他配置项
 * @returns {Promise} 请求Promise对象
 */
function del(url, data = {}, options = {}) {
  return request({
    url,
    method: 'DELETE',
    data,
    ...options
  });
}

/**
 * API请求助手
 * 用于处理加载状态、错误处理和数据转换
 * @param {Function} apiFunc API请求函数
 * @param {Object} options 配置选项
 * @returns {Object} API辅助对象
 */
function useApi(apiFunc, options = {}) {
  const loading = ref(false);
  const error = ref(null);
  const data = ref(null);
  
  // 默认选项
  const defaultOptions = {
    loadingText: '加载中...',
    errorText: '加载失败',
    showLoading: true,
    showError: true,
    transform: (data) => data,
    onSuccess: null,
    onError: null
  };
  
  // 合并选项
  const mergedOptions = { ...defaultOptions, ...options };
  
  // 执行API请求
  const execute = async (...args) => {
    try {
      loading.value = true;
      error.value = null;
      
      // 显示加载提示
      if (mergedOptions.showLoading) {
        uni.showLoading({
          title: mergedOptions.loadingText,
          mask: true
        });
      }
      
      // 调用API函数
      const result = await apiFunc(...args);
      
      // 转换数据
      data.value = mergedOptions.transform(result);
      
      // 调用成功回调
      if (typeof mergedOptions.onSuccess === 'function') {
        mergedOptions.onSuccess(data.value);
      }
      
      return data.value;
    } catch (err) {
      error.value = err;
      
      // 显示错误提示
      if (mergedOptions.showError) {
        uni.showToast({
          title: err.message || mergedOptions.errorText,
          icon: 'none'
        });
      }
      
      // 调用错误回调
      if (typeof mergedOptions.onError === 'function') {
        mergedOptions.onError(err);
      }
      
      throw err;
    } finally {
      loading.value = false;
      
      // 隐藏加载提示
      if (mergedOptions.showLoading) {
        uni.hideLoading();
      }
    }
  };
  
  return {
    loading,
    error,
    data,
    execute
  };
}

// 导出请求方法
export {
  request,
  get,
  post,
  put,
  del,
  useApi
};
